package com.mpgame.service;

import com.mpgame.battle.BattleRoom;
import com.mpgame.battle.BattleRoomMgr;
import com.mpgame.common.proto.BattleActionReq;
import com.mpgame.common.proto.BattleActionRsp;
import com.mpgame.common.proto.BattleAnimationFinishedPlayMsg;
import com.mpgame.common.proto.BattleAnimationFinishedPlayReq;
import com.mpgame.common.proto.BattleEndMsg;
import com.mpgame.common.proto.BattleInviteMsg;
import com.mpgame.common.proto.BattleInviteRefuseMsg;
import com.mpgame.common.proto.BattleInviteRefuseReq;
import com.mpgame.common.proto.BattleInviteRefuseRsp;
import com.mpgame.common.proto.BattleInviteReq;
import com.mpgame.common.proto.BattleInviteRsp;
import com.mpgame.common.proto.BattleMatchReq;
import com.mpgame.common.proto.BattleMatchRsp;
import com.mpgame.common.proto.BattleStartReq;
import com.mpgame.common.proto.BattleStartRsp;
import com.mpgame.common.proto.CmdId;
import com.mpgame.common.proto.StreamPacket;
import com.mpgame.common.proto.BattleServerServiceGrpc;
import com.mpgame.common.utils.Log;
import com.mpgame.common.helper.GrpcStreamHelper;
import com.mpgame.database.redis.utils.PlayerOnlineUtil;

import io.grpc.stub.StreamObserver;

public class BattleSvc extends BattleServerServiceGrpc.BattleServerServiceImplBase {
    private final BattleRoomMgr battleRoomMgr = BattleRoomMgr.getInstance();
    private volatile GrpcStreamHelper streamHelper;
    private static volatile BattleSvc instance;
    public static BattleSvc GetInstance(){
        if(instance == null){
            synchronized(BattleSvc.class){
                if(instance == null){
                    instance = new BattleSvc();
                }
            }
        }
        return instance;
    }
    private BattleSvc() {}

    @Override
    public StreamObserver<StreamPacket> battleStream(StreamObserver<StreamPacket> rspObs) {
        streamHelper = new GrpcStreamHelper(rspObs);
        BattleRoomMgr.getInstance().setStreamHelper(streamHelper);
        Log.info("BattleServer 建立新的流连接");
        return new StreamObserver<StreamPacket>() {
            @Override
            public void onNext(StreamPacket pkt) {
                try {
                    handleStreamPkt(pkt);
                } catch (Exception e) {
                    Log.err("处理流异常：" + e.getMessage());
                }
            }
            @Override
            public void onError(Throwable t) {
                Log.err("BattleServer 流连接错误：" + t.getMessage());
                streamHelper.setObs(null);
            }
            @Override
            public void onCompleted() {
                Log.info("BattleServer 流连接完成");
                streamHelper.setObs(null);
            }
        };
    }
    public void handleStreamPkt(StreamPacket pkt) {
        switch (pkt.getCmd()) {
            case BATTLE_ACTION_REQ:
                handleBattleActionStr(pkt);
                break;
            case BATTLE_ANIMATION_FINISHED_PLAY_REQ:
                handleBattleAnimationFinishedPlayStr(pkt);
                break;
            default:
                Log.warn("battleServer不处理流消息：" + pkt.getCmd());
                break;
        }
    }

    @Override
    public void battleInvite(BattleInviteReq req, StreamObserver<BattleInviteRsp> rspObs) {
        try {
            Log.info("收到对战邀请请求：" + req);
            BattleInviteRsp rsp = BattleInviteRsp.newBuilder()
                    .setInviterId(req.getAccountId())
                    .setInvitedId(req.getOpponentAccountId())
                    .setPayload(BattleInviteMsg.newBuilder()
                            .setInviterAccountId(req.getAccountId())
                            .setInviteMessage(
                                    "玩家 " + PlayerOnlineUtil.getPlayerName(req.getAccountId()) + " 向你发起对战邀请，是否接受？")
                            .build())
                    .build();
            rspObs.onNext(rsp);
            rspObs.onCompleted();
        } catch (Exception e) {
            Log.err("对战邀请请求异常：" + e.getMessage());
            BattleInviteRsp errRsp = BattleInviteRsp.newBuilder().setErrMsg("对战邀请请求异常：" + e.getMessage()).build();
            rspObs.onNext(errRsp);
            rspObs.onCompleted();
        }
    }

    @Override
    public void battleInviteRefuse(BattleInviteRefuseReq req, StreamObserver<BattleInviteRefuseRsp> rspObs) {
        try {
            Log.info("收到对战拒绝邀请请求：" + req);
            if (!PlayerOnlineUtil.isPlayerOnline(req.getInviterAccountId())) {
                BattleInviteRefuseRsp errRsp = BattleInviteRefuseRsp.newBuilder().setErrMsg("玩家不在线！").build();
                rspObs.onNext(errRsp);
                rspObs.onCompleted();
                return;
            }
            BattleInviteRefuseRsp rsp = BattleInviteRefuseRsp.newBuilder()
                    .setInviterAccountId(req.getInviterAccountId())
                    .setResultMsg("已拒绝对战邀请！")
                    .setPayload(BattleInviteRefuseMsg.newBuilder()
                            .setRefuseReason("对方拒绝了你的对战请求，原因：" + req.getRefuseReason()))
                    .build();
            rspObs.onNext(rsp);
            rspObs.onCompleted();
        } catch (Exception e) {
            Log.err("对战拒绝邀请请求异常：" + e.getMessage());
            BattleInviteRefuseRsp errRsp = BattleInviteRefuseRsp.newBuilder().setErrMsg("对战拒绝邀请请求异常：" + e.getMessage())
                    .build();
            rspObs.onNext(errRsp);
            rspObs.onCompleted();
        }
    }

    @Override
    public void battleMatch(BattleMatchReq req, StreamObserver<BattleMatchRsp> rspObs) {
        try {
            Log.info("收到匹配请求：玩家=" + req.getAccountId() + "，类型=" + req.getBattleType());
            BattleMatchRsp rsp = battleRoomMgr.requestMatch(req);
            rspObs.onNext(rsp);
            rspObs.onCompleted();
        } catch (Exception e) {
            Log.err("处理对战请求异常：" + e.getMessage());

            BattleMatchRsp errorResponse = BattleMatchRsp.newBuilder()
                    .setErrMsg("匹配失败: " + e.getMessage())
                    .build();

            rspObs.onNext(errorResponse);
            rspObs.onCompleted();
        }
    }

    @Override
    public void battleStart(BattleStartReq req, StreamObserver<BattleStartRsp> rspObs) {
        try {
            Log.info("收到开始对战请求...");
            BattleStartRsp rsp = battleRoomMgr.requestStartMatch(req);
            rspObs.onNext(rsp);
            rspObs.onCompleted();
        } catch (Exception e) {
            Log.err("处理对战开始异常：" + e.getMessage());
            BattleStartRsp errorResponse = BattleStartRsp.newBuilder()
                    .setErrMsg("匹配失败: " + e.getMessage())
                    .build();
            rspObs.onNext(errorResponse);
            rspObs.onCompleted();
        }
    }

    @Override
    public void battleAction(BattleActionReq req, StreamObserver<BattleActionRsp> rspObs) {
        try {
            BattleActionRsp rsp = battleRoomMgr.requestBattleAction(req);
            if (rsp != null) {
                rspObs.onNext(rsp);
                rspObs.onCompleted();
            } else {
                BattleActionRsp waitingRsp = BattleActionRsp.newBuilder()
                        .setErrMsg("等待对手出招...")
                        .build();
                rspObs.onNext(waitingRsp);
                rspObs.onCompleted();
            }
        } catch (Exception e) {
            Log.err("处理回合行动异常：" + e.getMessage());
            BattleActionRsp errorResponse = BattleActionRsp.newBuilder()
                    .setErrMsg("处理回合行动异常： " + e.getMessage())
                    .build();
            rspObs.onNext(errorResponse);
            rspObs.onCompleted();
        }
    }

    public void handlePlayerOffline(int accountId) {
        try {
            Log.info("收到玩家下线通知：" + accountId);
            battleRoomMgr.handlePlayerOffline(accountId);
        } catch (Exception e) {
            Log.err("处理玩家下线事件异常：" + e.getMessage());
        }
    }



    private void handleBattleActionStr(StreamPacket pkt) {
        int fromId = 0;
        try {
            BattleActionReq req = BattleActionReq.parseFrom(pkt.getData());
            fromId = req.getAccountId();
            BattleActionRsp rsp = battleRoomMgr.requestBattleAction(req);
            if (rsp != null) {
                if (rsp.getWinnerId() == -1) {
                    streamHelper.sendStreamPkt(rsp.getAccount1Id(), CmdId.BATTLE_ACTION_RESULT_MSG, rsp.getPayload1());
                    streamHelper.sendStreamPkt(rsp.getAccount2Id(), CmdId.BATTLE_ACTION_RESULT_MSG, rsp.getPayload2());
                } else {// 战斗结束，发送战斗结束消息
                    BattleEndMsg.Builder builder = BattleEndMsg.newBuilder();
                    streamHelper.sendStreamPkt(
                            rsp.getAccount1Id(),
                            CmdId.BATTLE_END_MSG,
                            builder.setIsWinner(rsp.getAccount1Id() == rsp.getWinnerId())
                                    .setContent(getWinnerContent(rsp.getAccount1Id() == rsp.getWinnerId()))
                                    .build());
                    streamHelper.sendStreamPkt(
                            rsp.getAccount2Id(),
                            CmdId.BATTLE_END_MSG,
                            builder.setIsWinner(rsp.getAccount2Id() == rsp.getWinnerId())
                                    .setContent(getWinnerContent(rsp.getAccount2Id() == rsp.getWinnerId()))
                                    .build());
                }
            } else {
                streamHelper.sendErrStreamPkt(req.getAccountId(), CmdId.BATTLE_ACTION_RESULT_MSG, "等待对手出招...");
            }
        } catch (Exception e) {
            Log.err("处理回合行动异常：" + e.getMessage());
            streamHelper.sendErrStreamPkt(fromId, CmdId.BATTLE_ACTION_RESULT_MSG, "处理回合行动失败！");
        }
    }

    private String getWinnerContent(boolean isWinner) {
        return isWinner ? "您取得了本次战斗的胜利！" : "胜败乃兵家常事，再接再厉！";
    }

    private void handleBattleAnimationFinishedPlayStr(StreamPacket pkt) {
        int fromId = 0;
        try {
            BattleAnimationFinishedPlayReq req = BattleAnimationFinishedPlayReq.parseFrom(pkt.getData());
            fromId = req.getAccountId();
            BattleRoom room = battleRoomMgr.getRoom(fromId);
            boolean isAllFinished = room.setFinishedAnim(fromId);
            if (isAllFinished) {
                BattleAnimationFinishedPlayMsg msg = BattleAnimationFinishedPlayMsg.newBuilder().build();
                streamHelper.sendStreamPkt(room.getPlayerIds(), CmdId.BATTLE_ANIMATION_FINISHED_PLAY_MSG, msg);
            }
        } catch (Exception e) {
            Log.err("处理动画播放完毕请求异常：" + e.getMessage());
            streamHelper.sendErrStreamPkt(fromId, CmdId.BATTLE_ANIMATION_FINISHED_PLAY_MSG, "处理动画播放完毕请求失败！");
        }
    }
}
